package com.artemis.event;

import com.artemis.*;
import com.artemis.systems.VoidEntitySystem;
import com.artemis.utils.*;

/**
 * An {@link EntitySystem} to queue events that should posted 
 * in the next process cycle.
 * This is useful if you want to post events from a different thread or
 * from the network.
 * Also useful to post events to systems that are processed before the current system processes.
 * 
 * This entity system should be the first system in the world.
 * 
 * @author kryo
 *
 */
public class EventQueuingSystem extends VoidEntitySystem {
	private Bag<SystemEvent> queue;
	
	public EventQueuingSystem() {
		queue = new Bag<SystemEvent>();
	}
	
	@Override
	protected void processSystem() {
		if(queue.isEmpty()) return;
		
		synchronized (queue) {
			for(int i = 0; i < queue.size(); i++) {
				world.postEvent(queue.get(i));
			}
			queue.clear();	
		}
	}

	/**
	 * Puts a {@link SystemEvent} onto the queue.
	 * The event will automatically posted (via {@link World#postEvent(SystemEvent)})
	 * in the next process cycle.
	 * @param e the event that should queued.
	 */
	public synchronized void pushEvent(SystemEvent e) {
		if(e == null) return;
		queue.add(e);
	}
	
	/**
	 * Returns the event queue.
	 * @return an {@link ImmutableBag} of events.
	 */
	public ImmutableBag<SystemEvent> getQueue() {
		return (ImmutableBag<SystemEvent>) queue;
	}
	
	/**
	 * Reduces the size of the backing array.
	 */
	public void shrink() {
		queue.shrink();
	}
}
